package cn.visu.security;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

import cn.visu.bean.Permission;
import cn.visu.dao.PermissionDao;
import cn.visu.security.filter.MyAuthenticationFilter;
import cn.visu.security.filter.MyPermissionAuthorizationFilter;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.MethodInvokingFactoryBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import com.alibaba.fastjson.JSON;

import cn.visu.security.realm.JdbcRealm;
import org.springframework.web.filter.DelegatingFilterProxy;

import javax.servlet.Filter;

/**
 * Shiro 配置
 */
@Configuration
public class ShiroConfiguration {

    /**
     * 初始化 缓存配置
     *
     * @return
     */
    @Bean("ehCacheManager")
    public EhCacheManager getEhCacheManager() {
        EhCacheManager em = new EhCacheManager();
        em.setCacheManagerConfigFile("classpath:ehcache.xml");
        return em;
    }

    /**
     * 向spring中注入 shiroFilter
     *
     * @return
     */
    @Bean
    public FilterRegistrationBean filterDemo4Registration() {
        FilterRegistrationBean registration = new FilterRegistrationBean();
        DelegatingFilterProxy delegatingFilterProxy = new DelegatingFilterProxy();
        delegatingFilterProxy.setTargetFilterLifecycle(true);
        //注入过滤器
        registration.setFilter(delegatingFilterProxy);
        //拦截规则
        registration.addUrlPatterns("/*");
        //过滤器名称
        registration.setName("shiroFilter");
        //是否自动注册 false 取消Filter的自动注册
        registration.setEnabled(false);
        //过滤器顺序
        registration.setOrder(1);
        return registration;
    }

    /**
     * 初始化自定义身份过滤器
     *
     * @return
     */
    @Bean("MyAuthenticationFilter")
    public MyAuthenticationFilter getMyAuthenticationFilter() {
        MyAuthenticationFilter myAuthenticationFilter = new MyAuthenticationFilter();
        return myAuthenticationFilter;
    }

    /**
     * 初始化自定义权限过滤器
     *
     * @return
     */
    @Bean("MyPermissionAuthorizationFilter")
    public MyPermissionAuthorizationFilter getMyPermissionAuthorizationFilter() {
        MyPermissionAuthorizationFilter myPermissionAuthorizationFilter = new MyPermissionAuthorizationFilter();
        return myPermissionAuthorizationFilter;
    }

    /**
     * 初始化配置  类似于 spring-shiro.xml
     *
     * @return
     */
    @Bean("CustomDefaultFilterChainManager")
    public CustomDefaultFilterChainManager getCustomDefaultFilterChainManager() {
        CustomDefaultFilterChainManager customDefaultFilterChainManager = new CustomDefaultFilterChainManager();
        //设置登录url
        customDefaultFilterChainManager.setLoginUrl("/login");
        //设置登录成功url
        customDefaultFilterChainManager.setSuccessUrl("/index");

        Map<String, Filter> map = new HashMap<String, Filter>();

        map.put("authc", getMyAuthenticationFilter());
        map.put("perms", getMyPermissionAuthorizationFilter());

        customDefaultFilterChainManager.setCustomFilters(map);

        Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
        filterChainDefinitionMap.put("/resource/**", "anon");
        filterChainDefinitionMap.put("/install", "anon");
        filterChainDefinitionMap.put("/**", "anon");
        customDefaultFilterChainManager.setFilterChainDefinitionMap(filterChainDefinitionMap);

        return customDefaultFilterChainManager;
    }

    /**
     * 生成过自定义过滤器链
     *
     * @return
     */
    @Bean("CustomPathMatchingFilterChainResolver")
    public CustomPathMatchingFilterChainResolver getCustomPathMatchingFilterChainResolver() {
        CustomPathMatchingFilterChainResolver customPathMatchingFilterChainResolver = new CustomPathMatchingFilterChainResolver();

        customPathMatchingFilterChainResolver.setCustomDefaultFilterChainManager(getCustomDefaultFilterChainManager());

        return customPathMatchingFilterChainResolver;
    }

    /**
     * 初始化 数据库中认证和权限信息
     *
     * @return
     */
    @Bean(name = "JdbcRealm")
    public JdbcRealm JdbcRealm() {
        JdbcRealm realm = new JdbcRealm();
        return realm;
    }

    /**
     * shiro 生命周期处理器
     * 用于在实现了Initializable接口的Shiro bean初始化时调用Initializable接口回调，
     * 在实现了Destroyable接口的Shiro bean销毁时调用 Destroyable接口回调
     * <p>
     * 例如JdbcRealm就实现了Initializable，
     * 而DefaultSecurityManager实现了Destroyable。
     * 具体可以查看它们的继承关系。
     *
     * @return
     */
    @Bean(name = "lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }


    /**
     * 开启 jdk类代理
     * shiro的代理是类代理 没有接口
     * 开启Shiro Spring AOP权限注解的支持；
     *
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator();
        daap.setProxyTargetClass(true);
        return daap;
    }

    /**
     * 初始化 securityManager
     *
     * @param jdbcRealm
     * @return
     */
    @Bean(name = "securityManager")
    public DefaultWebSecurityManager getDefaultWebSecurityManager(JdbcRealm jdbcRealm) {
        DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager();
        /**
         *  用户认证信息和权限信息
         */

        dwsm.setRealm(jdbcRealm);

        /**
         * 用户授权/认证信息Cache, 采用EhCache 缓存
         */
        dwsm.setCacheManager(getEhCacheManager());
        return dwsm;
    }

    /**
     * 开启shiro注解
     *
     * @param securityManager
     * @return
     */
    @Bean
    public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor(
            DefaultWebSecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor();
        aasa.setSecurityManager(securityManager);
        return aasa;
    }


    /**
     * ShiroFilter<br/>
     *
     * @return
     * @author SHANHY
     * @create 2016年1月14日
     */
    @Bean(name = "shiroFilter")
    public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager
    ) {

        MyShiroFilterFactoryBean shiroFilterFactoryBean = new MyShiroFilterFactoryBean();
        // 必须设置 SecurityManager

        shiroFilterFactoryBean.setSecurityManager(securityManager);

        shiroFilterFactoryBean.setPathMatchingFilterChainResolver(getCustomPathMatchingFilterChainResolver());

        SecurityUtils.setSecurityManager(securityManager);


        return shiroFilterFactoryBean;
    }


}